﻿
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows.Data;
using Red.Controls.ViewModels;
using Red.Core.Containers;

namespace BeefSandbox
{
    internal class TestDataItem_Simple<T> : DataItem where T : IConvertible
    {
        private T _val;
        private readonly string _group;

        public override string Type
        {
            get
            { // works as long as T fits one of Interop types (simple types as int, float etc. will do)
                var x = typeof( T ).Name;
                return x;
            }
        } 

        public override string Group { get { return _group; } }

        public override DataItemKind Kind { get { return DataItemKind.Simple; } }

        public override string Value
        {
            get
            {
                return _val.ToString();
            }

            set
            {
                var converter = TypeDescriptor.GetConverter( typeof( T ) );
                _val = (T)converter.ConvertFrom( value );
                OnPropertyChanged();
            }
        }

        public TestDataItem_Simple( DataItem parent, string name, T initialVal, string group = "" )
            : base( parent )
        {
            Title = name;
            _val = initialVal;
            _group = group;
        }
    }


    internal class TestDataItem_Ranged<T> : TestDataItem_Simple<T> where T : IConvertible
    {
        private readonly T _min;
        private readonly T _max;

        public TestDataItem_Ranged( DataItem parent, string name, T val, T min, T max, string group = "" )
            : base( parent, name, val, group )
        {
            _min = min;
            _max = max;
        }

        public override string Type
        {
            get
            {
                return typeof( T ).Name + ":Ranged";
            }
        }

        protected override Task EnumerateChildrenAsync( IRangedCollection<DataItem> children )
        {
            children.Clear();
            children.Add( new TestDataItem_Simple<T>( this, "_min", _min ) );
            children.Add( new TestDataItem_Simple<T>( this, "_max", _max ) );
            return Task.CompletedTask;
        }
    }

    internal class TestDataItem_Vector<T> : DataItem where T : IConvertible
    {
        private readonly string _group;
        private T _x, _y, _z;

        public override string Value { get { return ""; } set { } }

        public override string Type { get { return "Vector"; } }

        public override string Group { get { return _group; } }

        public override DataItemKind Kind { get { return DataItemKind.Compound; } }

        public TestDataItem_Vector( DataItem parent, string name, T x, T y, T z, string group = "" )
            : base( parent )
        {
            Title = name;
            _group = group;
            _x = x;
            _y = y;
            _z = z;
        }

        protected override Task EnumerateChildrenAsync( IRangedCollection<DataItem> children )
        {
            children.Clear();
            children.Add( new TestDataItem_Simple<T>( this, "X", _x ) );
            children.Add( new TestDataItem_Simple<T>( this, "Y", _y ) );
            children.Add( new TestDataItem_Simple<T>( this, "Z", _z ) );
            return Task.CompletedTask;
        }
    }

    internal class TestDataItem_Root : DataItem
    {
        public override string Type { get { return ""; } }

        public override string Value { get { return ""; } set { } }

        public override DataItemKind Kind { get { return DataItemKind.Compound; } }

        public TestDataItem_Root()
            : base( null )
        {
            CollectionView collectionView = (CollectionView)CollectionViewSource.GetDefaultView( Children );
            PropertyGroupDescription groupDescription = new PropertyGroupDescription( "Group" );
            collectionView.GroupDescriptions.Add( groupDescription );
        }

        protected override Task EnumerateChildrenAsync( IRangedCollection<DataItem> children )
        {
            children.Clear();
            children.Add( new TestDataItem_Simple<int>( this, "simple int", 5, "group 1" ) );
            children.Add( new TestDataItem_Simple<float>( this, "simple float", 5.0f, "group 1" ) );
            children.Add( new TestDataItem_Ranged<int>( this, "ranged", 15, 10, 20, "group 2" ) );
            children.Add( new TestDataItem_Ranged<int>( this, "ranged 2", 150, 100, 200, "group 2" ) );
            children.Add( new TestDataItem_Vector<int>( this, "vector", 1, 2, 3, "group 2" ) );
            children.Add( new TestDataItem_Simple<float>( this, "ungrouped", 42.0f ) );
            children.Add( new TestDataItem_Simple<float>( this, "", 5.0f ) );
            return Task.CompletedTask;
        }
    }
}
